package br.edu.ufcg.mdaveritas.parser.output;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;


import org.w3c.dom.Document;
import org.w3c.dom.Element;

import br.edu.ufcg.mdaveritas.net.Node;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

@SuppressWarnings("restriction")
public class EcoreGenerator {

	private Document dom;
	private List<br.edu.ufcg.mdaveritas.net.Node> nodes;

	public EcoreGenerator(List<br.edu.ufcg.mdaveritas.net.Node> nodes) {
		this.nodes = nodes;
		createDocument();
	}

	public void createXML(String filePath) {
		createDOMTree();
		printToFile(filePath);
	}

	private void createDocument() {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			dom = db.newDocument();
		} catch (ParserConfigurationException pce) {
			System.out
					.println("Error while trying to instantiate DocumentBuilder "
							+ pce);
			System.exit(1);
		}

	}

	private void createDOMTree() {
		Element rootEle = createPNMLElement();
		dom.appendChild(rootEle);
	}

	private Element createPlaceElement(Node plc) {
		Element plcEle = dom.createElement("objects");
		plcEle.setAttribute("id", "");
		plcEle.setAttribute("xsi:type", "ptnet:Place");
		plcEle.appendChild(createName(plc.getName()));
		plcEle.appendChild(createGraphics());
		plcEle.appendChild(createInitialMarking("0"));
		return plcEle;
	}

	private Element createTransitionElement(Node t) {
		Element tEle = dom.createElement("objects");
		tEle.setAttribute("id", "");
		tEle.setAttribute("xsi:type", "ptnet:Transition");
		tEle.appendChild(createName(t.getName()));
		tEle.appendChild(createGraphics());
		return tEle;
	}

	private Element createName(String name) {
		Element nameEle = dom.createElement("name");
		nameEle.setAttribute("text", name);

		return nameEle;
	}

	private Element createGraphics() {
		Element posEle = dom.createElement("position");
		posEle.setAttribute("x", "0");
		posEle.setAttribute("y", "0");
		Element dimEle = dom.createElement("dimension");
		dimEle.setAttribute("x", "0");
		dimEle.setAttribute("y", "0");
		Element fillEle = dom.createElement("fill");
		fillEle.setAttribute("color", "WHITE");
		Element lineEle = dom.createElement("line");
		lineEle.setAttribute("width", "1");
		Element graphicsEle = dom.createElement("nodegraphics");
		graphicsEle.appendChild(posEle);
		graphicsEle.appendChild(dimEle);
		graphicsEle.appendChild(fillEle);
		graphicsEle.appendChild(lineEle);
		return graphicsEle;
	}

	private Element createInitialMarking(String marking) {
		Element markEle = dom.createElement("initialMarking");
		markEle.setAttribute("text", "0");

		return markEle;
	}

	private Element createPageElement(List<Node> nodes, int id) {
		Element pageEle = dom.createElement("pages");
		pageEle.setAttribute("id", String.valueOf(id));

		for (Node node : nodes) {
			if (node.getSubnet() == id) {
				if (node.getIsPlace()) {
					Element plcEle = createPlaceElement(node);
					pageEle.appendChild(plcEle);
				} else {
					Element tEle = createTransitionElement(node);
					pageEle.appendChild(tEle);
				}
			}
		}

		return pageEle;
	}

	private Element createPNMLElement() {
		Element pnmlEle = dom.createElement("ptnet:PetriNet");
		pnmlEle.setAttribute("xmi:version", "2.0");
		pnmlEle.setAttribute("xmlns:xmi", "http://www.omg.org/XMI");
		pnmlEle.setAttribute("xmlns:xsi",
				"http://www.w3.org/2001/XMLSchema-instance");
		pnmlEle.setAttribute("xmlns:ptnet", "http:///ptnet.ecore");
		pnmlEle.setAttribute("id", "subnets");
		
		List<Integer> pages = new ArrayList<Integer>();
		
		for (Node n : nodes) {
			if (!pages.contains(n.getSubnet())) {
				pages.add(n.getSubnet());
			}
		}
		
		for (int i : pages) {
			Element pageEle = createPageElement(nodes, i);
			pageEle.appendChild(createGraphics());
			pnmlEle.appendChild(pageEle);	
		}
		
		return pnmlEle;
	}

	private void printToFile(String filePath) {

		try {
			OutputFormat format = new OutputFormat(dom);
			format.setIndenting(true);

			XMLSerializer serializer = new XMLSerializer(new FileOutputStream(
					new File(filePath)), format);

			serializer.serialize(dom);

		} catch (IOException ie) {
			ie.printStackTrace();
		}
	}
}